/**
 * 
 */
package com.dhcc.cdbp.createindex;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;

import java.io.IOException;

import org.apache.lucene.analysis.core.WhitespaceAnalyzer;
import org.apache.lucene.document.Document;
import org.apache.lucene.document.Field;
import org.apache.lucene.document.NumericDocValuesField;
import org.apache.lucene.document.StringField;
import org.apache.lucene.index.DirectoryReader;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.index.IndexWriter;
import org.apache.lucene.index.IndexWriterConfig;
import org.apache.lucene.index.IndexWriterConfig.OpenMode;
import org.apache.lucene.index.Term;
import org.apache.lucene.search.IndexSearcher;
import org.apache.lucene.search.Query;
import org.apache.lucene.search.TermQuery;
import org.apache.lucene.store.Directory;
import org.apache.lucene.store.RAMDirectory;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import com.dhcc.cdbp.util.TestUtil;

/**
 * @author 谢进军
 *
 */
public class IndexingTest {
	protected String[] ids = {"1","2"};
	protected String[] unindexed = {"Netherlands","Italy"};
	protected String[] unstored = {"Amsterdam has lots of bridges","Venice has lots of canals"};
	protected String[] text = {"Amsterdam","Venice"};
	private Directory directory;
	
	@Before
	public void setUp() throws Exception {
		directory = new RAMDirectory();
		IndexWriter writer = getIndexWriter(true);
		for (int i = 0; i < ids.length; i++) {
			Document doc = new Document();
			doc.add(new StringField("id",ids[i],Field.Store.YES));
			doc.add( new StringField("country", unindexed[i], Field.Store.YES));
			doc.add( new StringField("contents", unstored[i], Field.Store.NO));
			doc.add( new StringField("city", text[i], Field.Store.YES));
			writer.addDocument(doc);
		}
		writer.close();
	}
	@Test public void testIndexWriter() throws IOException{
		IndexWriter  writer = getIndexWriter(false);
		assertEquals(ids.length, writer.numDocs());
		writer.close();
	}
	@Test public void testIndexReader() throws IOException{
		IndexReader reader = DirectoryReader.open(directory);
		assertEquals(ids.length, reader.maxDoc());
		assertEquals(ids.length, reader.numDocs());
		reader.close();
	}
	protected int getHitCount(String fieldName,String searchString) throws IOException {
		IndexSearcher searcher = new IndexSearcher(DirectoryReader.open(directory));
		Term t = new Term(fieldName, searchString);
		Query query = new TermQuery(t);
		int hitCount =TestUtil.hitCount(searcher, query);
	    return hitCount;
	}
	/**
	 * IndexWriter支持三种打开模型：
	 * 		create:Creates a new index or overwrites an existing one.
	 * 		APPEND:Opens an existing index. 如果索引不存在就会抛出IndexNotFoundException
	 * 		CREATE_OR_APPEND:Creates a new index if one does not exist, otherwise it opens the index and documents will be appended. 
	 * @param createOrAppend
	 * @return
	 * @throws IOException
	 */
	private IndexWriter getIndexWriter(boolean createOrAppend) throws IOException {
		IndexWriterConfig iwc = new IndexWriterConfig(new WhitespaceAnalyzer());
		if (createOrAppend) {
			iwc.setOpenMode(OpenMode.CREATE);
		}else {
			iwc.setOpenMode(OpenMode.CREATE_OR_APPEND);
		}
		return new IndexWriter(directory,iwc);
	}
	/**
	 * hasDeletions():用于检查索引中是否包含被标记为已删除的文档
	 * maxDoc():返回索引中被删除和未被删除的文档总数
	 * numDoc():返回索引中未被删除的文档总数
	 * @throws IOException
	 */
	@Test public void testDeleteBeforeOptimize() throws IOException{
		IndexWriter writer = getIndexWriter(false);
		assertEquals(2, writer.maxDoc());
		assertEquals(2, writer.numDocs());
		writer.deleteDocuments(new Term("id","1"));
		writer.commit();
		assertTrue(writer.hasDeletions());
		assertEquals(2, writer.maxDoc());
		assertEquals(1, writer.numDocs());
		writer.close();
	}
	@Test public void testDeleteAfterOptimize() throws IOException{
		IndexWriter writer = getIndexWriter(false);
		assertEquals(2, writer.maxDoc());
		assertEquals(2, writer.numDocs());
		writer.deleteDocuments(new Term("id","1"));
		writer.forceMergeDeletes();//删除文档后合并索引段
		writer.commit();
		assertFalse(writer.hasDeletions());
		assertEquals(1, writer.maxDoc());
		assertEquals(1, writer.numDocs());
		writer.close();
	}
	@Test public void testUpdate() throws IOException{
		assertEquals(1, getHitCount("city", "Amsterdam"));
		IndexWriter writer = getIndexWriter(true);
		Document doc = new Document();
		doc.add( new StringField("id", "1", Field.Store.YES));
		doc.add( new StringField("country", "Netherlands", Field.Store.YES));
		doc.add( new StringField("contents", "Den Haag has a lot of museums", Field.Store.NO));
		doc.add( new StringField("city", "Den Haag", Field.Store.YES));
		doc.add( new NumericDocValuesField("xx", 1));
		writer.updateDocument(new Term("id","1"), doc);
		writer.close();
		assertEquals(0,getHitCount("city", "Amsterdam") );
		assertEquals(1,getHitCount("city", "Den Haag") );
	}
	@After
	public void tearDown() throws Exception {
	}
}
